package com.dmwork.service.work.mq.sender;

import com.dmwork.service.work.mq.callback.ConfirmCallback;
import com.dmwork.service.work.mq.callback.ReturnCallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import reactor.util.annotation.NonNull;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Component
public class MessageSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private ReturnCallback returnCallback;
    @Autowired
    private ConfirmCallback confirmCallback;

    //WorkPublish
    @Value("${spring.rabbitmq.custom.sender.send-work-publish-message.exchange}")
    private String sendWorkPublishMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-work-publish-message.routekey}")
    private String sendWorkPublishMessageRouteKey;

    //single file remove
    @Value("${spring.rabbitmq.custom.sender.send-single-file-remove-message.exchange}")
    private String sendSingleFileRemoveMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-single-file-remove-message.routekey}")
    private String sendSingleFileRemoveMessageRoutekey;

    //batch file remove
    @Value("${spring.rabbitmq.custom.sender.send-batch-file-remove-message.exchange}")
    private String sendBatchFileRemoveMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-batch-file-remove-message.routekey}")
    private String sendBatchFileRemoveMessageRoutekey;

    //batch video remove
    @Value("${spring.rabbitmq.custom.sender.send-batch-video-remove-message.exchange}")
    private String sendBatchVideoRemoveMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-batch-video-remove-message.routekey}")
    private String sendBatchVideoRemoveMessageRoutekey;

    //work publish feed remove
    @Value("${spring.rabbitmq.custom.sender.send-work-publish-feed-remove-message.exchange}")
    private String sendWorkPublishFeedMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-work-publish-feed-remove-message.routekey}")
    private String sendWorkPublishFeedMessageRoutekey;

    //admin remove work
    @Value("${spring.rabbitmq.custom.sender.send-admin-remove-work-system-message.exchange}")
    private String sendAdminRemoveWorkSystemMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-admin-remove-work-system-message.routekey}")
    private String sendAdminRemoveWorkSystemMessageRoutekey;

    /**
     * 向动态功能所在模块发送新投稿作品的消息
     *
     * @param message
     * @param properties
     */
    public void sendWorkPublishMessage(Map<String, Object> message, @NonNull Map<String, Object> properties) {
        Message<Map<String, Object>> msg = processRabbitTemplate(message, properties, ConfirmCallback.WORK_PUBLISH_CONFIRM, ReturnCallback.WORK_PUBLISH_RETURN);
        rabbitTemplate.convertAndSend(sendWorkPublishMessageExchange, sendWorkPublishMessageRouteKey, msg, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * 向oss模块投递包含要删除的文件url的信息，让oss去将该url对应的文件删除
     *
     * @param url        要删除的文件url
     * @param properties 自定义属性
     */
    public void sendSingleFileRemoveMessage(String url, @NonNull Map<String, Object> properties) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("url", url);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.SINGLE_FILE_REMOVE_CONFIRM, ReturnCallback.SINGLE_FILE_REMOVE_RETURN);
        rabbitTemplate.convertAndSend(sendSingleFileRemoveMessageExchange, sendSingleFileRemoveMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * 向oss模块投递包含要删除的多个文件url的信息，让oss去将该url对应的文件批量删除
     *
     * @param urlList    文件url列表
     * @param properties 自定义属性
     */
    public void sendBatchFileRemoveMessage(List<String> urlList, @NonNull Map<String, Object> properties) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("urlList", urlList);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.BATCH_FILE_REMOVE_CONFIRM, ReturnCallback.BATCH_FILE_REMOVE_RETURN);
        rabbitTemplate.convertAndSend(sendBatchFileRemoveMessageExchange, sendBatchFileRemoveMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * 向MQ投递包含要删除的多个视频资源的id的消息，让vod去批量删除视频
     * @param videoIdList 视频资源id列表
     * @param properties 自定义属性
     */
    public void sendBatchVideoRemoveMessage(List<String> videoIdList, @NonNull Map<String, Object> properties) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("videoIdList", videoIdList);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.BATCH_VIDEO_REMOVE_CONFIRM, ReturnCallback.BATCH_VIDEO_REMOVE_RETURN);
        rabbitTemplate.convertAndSend(sendBatchVideoRemoveMessageExchange, sendBatchVideoRemoveMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * 向MQ投递包含指定作品id的消息，让interaction模块去删除该作品发布时产生的动态
     * @param workId 作品id
     * @param properties 自定义属性
     */
    public void sendWorkPublishFeedRemoveMessage(String workId,@NonNull Map<String, Object> properties) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("workId", workId);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.WORK_PUBLISH_FEED_REMOVE_CONFIRM, ReturnCallback.WORK_PUBLISH_FEED_REMOVE_RETURN);
        rabbitTemplate.convertAndSend(sendWorkPublishFeedMessageExchange, sendWorkPublishFeedMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     *
     * @param customerId 通知的用户id
     * @param workTitle 被删除的作品的标题
     * @param properties
     */
    public void sendAdminRemoveWorkSystemMessage(String customerId, String workTitle, @NonNull Map<String, Object> properties) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("customerId", customerId);
        messageMap.put("title", workTitle);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.ADMIN_REMOVE_WORK_CONFIRM, ReturnCallback.ADMIN_REMOVE_WORK_RETURN);
        rabbitTemplate.convertAndSend(sendAdminRemoveWorkSystemMessageExchange, sendAdminRemoveWorkSystemMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }


    ///////////// 私有工具方法/////////////////
    /**
     * 处理并返回封装的消息对象，且分别设置确认机制和返回机制要调用的方法名
     * @param message 自定义消息对象
     * @param properties 自定义属性
     * @param confirmCallbackMethodName 消息确认回调方法名
     * @param returnCallbackMethodName 消息返回机制回调方法名
     * @param <T>
     * @return
     */
    private <T> Message<T> processRabbitTemplate(T message, Map<String, Object> properties, String confirmCallbackMethodName, String returnCallbackMethodName) {
        MessageHeaders headers = new MessageHeaders(properties);
        Message<T> msg = MessageBuilder.createMessage(message, headers);
        //分别设置确认机制和返回机制要调用的方法名
        confirmCallback.setCallbackName(confirmCallbackMethodName);
        returnCallback.setCallbackName(returnCallbackMethodName);

        rabbitTemplate.setConfirmCallback(confirmCallback.originalConfirmCallback);
        rabbitTemplate.setReturnCallback(returnCallback.originalReturnCallback);
        return msg;
    }

}
